package com.cise.sort.linear;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import org.junit.Test;

import com.cise.searcher.utils.Result;
import com.cise.services.impl.SearchServiceImpl;

public class Chromosome {
	private int geneNum;
	private double[] genes = null;
	private double fitness = -1;
	private final static double GENE_MUTATION_PROBABILITY = 0.1; 
	
	public Chromosome(int geneNum) {
		this.geneNum = geneNum;
		this.genes = new double[this.geneNum];
	}
	
	public int getGeneNum() {
		return geneNum;
	}

	public double[] getGenes() {
		return genes;
	}

	public void setGenes(double[] genes) {
		this.genes = genes;
	}

	public double getFitness() {
		return fitness;
	}

	public void randomCreateGenes(){
		this.genes = new double[this.geneNum];
		Random random = new Random();
		double total = 0;
		for(int i = 0; i < this.geneNum; i++){
			this.genes[i] = random.nextDouble();
			total += this.genes[i];
		}
		for(int i = 0; i < this.geneNum; i++){
			this.genes[i] /= total;
		}
	}
	
	public void calculateFitness(String input, List<String> list){
		if(this.fitness < 0){
			this.fitness = 0;
			File file = new File(input);
			SearchServiceImpl searchServiceImpl = new SearchServiceImpl(file);
			searchServiceImpl.setFeatureWeight(this.genes);
			List<Result> results = searchServiceImpl.search();
			for(int i = 0; i < results.size(); i++){
				if(list.indexOf(results.get(i).getPath()) >= 0){
					System.out.println(i + " " + results.get(i).getPath() + " " + results.get(i).getDistance());
					this.fitness += Math.pow(0.5, i);
				}
			}
		}
	}
	
	public Chromosome recombinant(Chromosome ch){
		Chromosome chromosome = new Chromosome(this.geneNum);
		double[] genes = new double[this.geneNum];
		for(int i = 0; i < this.geneNum; i++){
			genes[i] = (this.genes[i] + ch.getGenes()[i]) / 2;
		}
		chromosome.setGenes(genes);
		return chromosome;
	}
	
	public void geneMutation(){
		Random random = new Random();
		if(random.nextDouble() < GENE_MUTATION_PROBABILITY){
			for(int i = 0; i < this.geneNum / 2; i++){
				int index1 = i * 2;
				int index2 = index1 + 1;
				if(this.genes[index1] > this.genes[index2]){
					int t = index1;
					index1 = index2;
					index2 = t;
				}
				// -1*this.genes[index1] <= diff <= this.genes[index1]
				double diff = (random.nextDouble() * 2 - 1) * this.genes[index1];
				this.genes[index1] += diff;
				this.genes[index2] -= diff;
			}
		}
	}

	@Override
	public String toString() {
		return "Chromosome [genes=" + Arrays.toString(genes) + ", fitness="
				+ fitness + "]";
	}
	
}
